/**
 * 
 */
package com.arx.time;

import com.arx.common.Common;

/**
 * @author Donald
 */
public final class Time {
	/** the singleton instance. */
	private static Time	instance;
	/**
	 * Gets the one and only instance of {@link Time}.
	 * @return {@link Time}
	 */
	public static Time getInstance() {
		if (Time.instance == null) {
			Time.instance = new Time();
		}
		return Time.instance;
	}
	private float	ARXPausedTime		= 0;
	private boolean	ARXPausedTimer		= false;
	private float	ARXTime				= 0;
	private float	ARXTotalPausedTime	= 0;
	private boolean	bTimerInit			= false;
	private float	FrameTime;
	private float	LastFrameTime;					// ARX: jycorbel
	private long	timerStart;
	// (2010-07-19) - Add
	// external vars for
	// resetting them on
	// ARX_TIME_Init call.
	/** Hidden constructor. */
	private Time() {}
	/**
	 * Gets the number of nanoseconds that have passed since the game was
	 * started.
	 * @return float
	 */
	private float _ARX_TIME_GetTime() {
	
	_ARX_TIME_Init();
		long now = System.nanoTime();
		return now - timerStart;
	}
	/** Hidden method to start the game timer. */
	private void _ARX_TIME_Init() {
		if (!bTimerInit) {
			timerStart = System.nanoTime();
			bTimerInit = true;
			ARX_TIME_Init();
		}
	}
	/**
	 * Resets the timer - possibly due to lag when between game screens.
	 * @param time the time to which the timers are being reset
	 */
	public void ARX_TIME_Force_Time_Restore(final float time) {
		float tim = _ARX_TIME_GetTime();
		ARXTotalPausedTime = tim - time;
		ARXTime = time;
		ARXPausedTime = 0;
		ARXPausedTimer = false;
	}
	public float ARX_TIME_Get() {
		return ARX_TIME_Get(true);
	}
	public float ARX_TIME_Get(final boolean usePause) {
		float tim = _ARX_TIME_GetTime();
	
	if (ARXPausedTimer && usePause) {
			ARXTime = tim - ARXTotalPausedTime - (tim - ARXPausedTime);
		} else {
			ARXTime = tim - ARXTotalPausedTime;
		}
		return ARXTime;
	}
	public long ARX_TIME_GetUL() {
		return this.ARX_TIME_GetUL(true);
	}
	public long ARX_TIME_GetUL(boolean _bUsePause) {
		float time = ARX_TIME_Get(_bUsePause);
		time = Common.getInstance().checkUnsignedLongValue(ARXTime);
		return (long) time;
	}
	/** Initializes the game timer. */
	public void ARX_TIME_Init() {
		_ARX_TIME_Init();
		float tim = _ARX_TIME_GetTime();
		ARXTotalPausedTime = tim;
		ARXTime = 0;
		ARXPausedTime = 0;
		ARXPausedTimer = false;
		// ARX_BEGIN: jycorbel (2010-07-19) - Add external vars for
		// resetting them on ARX_TIME_Init call.
		// Currently when ARX_TIME_Init
		// the substract FrameDiff = FrameTime - LastFrameTime
		// is negative because of resetting ARXTotalPausedTime.
		// This solution reinit FrameTime & LastFrameTime to get a min
		// frameDiff = 0 on ARX_TIME_Init.
		FrameTime = LastFrameTime = ARXTime;
		// ARX_END: jycorbel (2010-07-19)
	}
	/** Pauses the game, and sets the time at which the pause started. */
	public void ARX_TIME_Pause() {
		if (!ARXPausedTimer) {
			// get the current time
			float tim = _ARX_TIME_GetTime();
			// store the time the pause started in a field
			ARXPausedTime = tim;
			// set the paused flag
			ARXPausedTimer = true;
		}
	}
	/** Unpauses the game, and updates the time spent paused. */
	public void ARX_TIME_UnPause() {
		if (ARXPausedTimer) {
			// get the current time
			float tim = _ARX_TIME_GetTime();
			// update the amount of time spent paused
			ARXTotalPausedTime += tim - ARXPausedTime;
			// remove the time the pause was started
			ARXPausedTime = 0;
			// remove the paused flag
			ARXPausedTimer = false;
		}
	}
	public long ARXTimeUL() {
		ARXTime = Common.getInstance().checkUnsignedLongValue(ARXTime);
		return (long) ARXTime;
	}
	/**
	 * Gets the aRXPausedTime
	 * @return {@link float}
	 */
	public float getARXPausedTime() {
		return ARXPausedTime;
	}
	/**
	 * Gets the aRXTime
	 * @return {@link float}
	 */
	public float getARXTime() {
		return ARXTime;
	}
	/**
	 * Gets the aRXTotalPausedTime
	 * @return {@link float}
	 */
	public float getARXTotalPausedTime() {
		return ARXTotalPausedTime;
	}
	/**
	 * Gets the frameTime
	 * @return {@link float}
	 */
	public float getFrameTime() {
		return FrameTime;
	}
	/**
	 * Gets the aRXPausedTimer
	 * @return {@link boolean}
	 */
	public boolean isARXPausedTimer() {
		return ARXPausedTimer;
	}
}